package cn.lili.common.security.context;

import cn.lili.cache.Cache;
import cn.lili.cache.CachePrefix;
import cn.lili.common.enums.ResultCode;
import cn.lili.common.exception.ServiceException;
import cn.lili.common.security.AuthUser;
import cn.lili.common.security.enums.SecurityEnum;
import cn.lili.common.security.token.SecretKeyUtil;
import com.alibaba.fastjson.JSONObject;
import com.google.gson.Gson;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.ExpiredJwtException;
import io.jsonwebtoken.Jwts;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;

/**
 * 用户上下文
 *
 * @author Chopper
 * @version v4.0
 * @since 2020/11/14 20:27
 */
@Slf4j
public class UserContext {

    private UserContext() {
        throw new IllegalStateException("Utility class");
    }

    /**
     * 根据request获取用户信息
     *
     * @return 授权用户
     */
    public static AuthUser getCurrentUser(Object ... objects) {
        //log.info("getCurrentUser == {}", JSONObject.toJSONString(objects));
        if (RequestContextHolder.getRequestAttributes() != null) {
            HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
            String accessToken = request.getHeader(SecurityEnum.HEADER_TOKEN.getValue());
            //log.info("accessToken == {}", accessToken);
            return getAuthUser(accessToken);
        }
        //log.info("token为空");
        return null;
    }

    /**
     * 根据不同的角色返回不同的id
     *
     * @return 授权用户
     */
    public static String getCurrentId() {
        if (RequestContextHolder.getRequestAttributes() != null) {
            HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
            String accessToken = request.getHeader(SecurityEnum.HEADER_TOKEN.getValue());
            AuthUser authUser = getAuthUser(accessToken);
            if (authUser == null) {
                throw new ServiceException(ResultCode.OAUTH_CODE_EMPTY);
            }
            return authUser.getExtendId();
        }
        return null;
    }

    /**
     * 根据request获取用户信息
     *
     * @return 授权用户
     */
    public static String getUuid() {
        if (RequestContextHolder.getRequestAttributes() != null) {
            HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
            return request.getHeader(SecurityEnum.UUID.getValue());
        }
        return null;
    }


    /**
     * 根据jwt获取token重的用户信息
     *
     * @param cache       缓存
     * @param accessToken token
     * @return 授权用户
     */
    public static AuthUser getAuthUser(Cache cache, String accessToken) {
        AuthUser authUser = getAuthUser(accessToken);
        if (authUser == null || cache.get(CachePrefix.ACCESS_TOKEN.getPrefix(authUser.getScene(), authUser.getId()) + accessToken) == null) {
            throw new ServiceException(ResultCode.USER_AUTHORITY_ERROR);
        }
        return authUser;
    }

    /**
     * 根据jwt获取token重的用户信息
     *
     * @param accessToken token
     * @return 授权用户
     */
    public static AuthUser getAuthUser(String accessToken) {
        try {
            //获取token的信息
            Claims claims
                    = Jwts.parserBuilder().setSigningKey(SecretKeyUtil.generalKeyByDecoders()).build().parseClaimsJws(accessToken).getBody();
            //获取存储在claims中的用户信息
            String json = claims.get(SecurityEnum.USER_CONTEXT.getValue()).toString();
            return new Gson().fromJson(json, AuthUser.class);
        } catch (ExpiredJwtException eje) {
            throw new ServiceException(ResultCode.USER_AUTH_EXPIRED);
        } catch (Exception e) {
            return null;
        }
    }
}
